﻿namespace Resonator.Core.Services
{
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.ComponentModel.Design;
	using System.Globalization;
	using System.IO;
	using System.Resources;
	using Models;
	using Resonator.Domain.Models;
	using Resonator.Domain.Services;

	public class ResxResourceParser : IResourceParser
	{
		public virtual IList<Resource> Parse(ResourceStream resourceStream)
		{
			return Parse( resourceStream, CultureInfo.InvariantCulture );
		}

		public virtual IList<Resource> Parse(ResourceStream resourceStream, CultureInfo defaultCulture)
		{
			if( resourceStream == null )
			{
				throw new ArgumentNullException( "resourceStream" );
			}
			if( defaultCulture == null )
			{
				throw new ArgumentNullException( "defaultCulture" );
			}

			List<Resource> resources = new List<Resource>();
			CultureInfo resourceFileCulture = ExtractCultureFromResourceStream( resourceStream, defaultCulture );
			string resourceNamePrefix = GetFileNameWithoutExtensionOrCulture( resourceStream );

			try
			{
				using( ResXResourceReader reader = new ResXResourceReader( new NoCloseStream( resourceStream.Stream ) ) )
				{
					reader.UseResXDataNodes = true;
					foreach( DictionaryEntry entry in reader )
					{
						ResXDataNode node = (ResXDataNode)entry.Value;
						if( IsResourceNode( node ) )
						{
							Resource resource = new Resource();
							resource.Culture = resourceFileCulture;
							resource.Name = string.Concat( resourceNamePrefix, ".", node.Name );
							resource.Phrase = node.GetValue( (ITypeResolutionService)null ) as string;
							resource.Context = node.Comment;
							resources.Add( resource );
						}
					}
				}
			}
			catch( Exception exc )
			{
				throw new ResonatorException( "Unable to parse Resources from stream '{0}'", exc, resourceStream.Name );
			}

			return resources;
		}

		protected virtual CultureInfo ExtractCultureFromResourceStream(ResourceStream stream, CultureInfo defaultCulture)
		{
			string fileName = Path.GetFileNameWithoutExtension( stream.Name );

			int cultureExtension = fileName.LastIndexOf( '.' );
			if( cultureExtension == -1 )
			{
				return defaultCulture;
			}

			string cultureName = fileName.Substring( cultureExtension + 1 );
			try
			{
				return new CultureInfo( cultureName );
			}
			catch
			{
				return defaultCulture;
			}
		}

		protected virtual string GetFileNameWithoutExtensionOrCulture(ResourceStream stream)
		{
			string fileName = Path.GetFileNameWithoutExtension( stream.Name );

			int cultureExtension = fileName.LastIndexOf( '.' );
			if( cultureExtension == -1 )
			{
				return fileName;
			}
			else
			{
				return fileName.Substring( 0, cultureExtension );
			}
		}

		protected virtual bool IsResourceNode(ResXDataNode node)
		{
			if( string.IsNullOrEmpty( node.Name ) )
			{
				return false;
			}
			if( node.Name.EndsWith( ".Text" ) )
			{
				return true;
			}
			if( node.Name.EndsWith( ".HeaderText" ) )
			{
				return true;
			}
			if( node.Name.EndsWith( ".NullText" ) )
			{
				return true;
			}
			if( node.Name.IndexOf( '.' ) < 0 )
			{
				return true;
			}
			return false;
		}
	}
}